home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////////
- // UTILCLS.H - Utility Classes
- //
- // $Revision: 1.0.3.12 $
- // $Date: 03 Feb 1998 18:45:10 $
- //
- // Copyright (c) 1998 Borland International
- /////////////////////////////////////////////////////////////////////////////
- #ifndef __UTILCLS_H
- #define __UTILCLS_H
-
- #include <objbase.h>
- #include <oleauto.h>
- #include <cguid.h>
- #include <stdarg.h>
- #include <tchar.h>
-
- // Forward ref.
- //
- template <class DISPINTF = IDispatch>
- class TAutoDriver;
- template <class T>
- class TDebugHlpr;
-
- // Macros
- //
-
- // CONNECTIONPOINT_ARRAY_SIZE is used by the Fire_xxxx Event templates generated for
- // outgoing interfaces in the xxxx_TLB.H file.
- //
- #if !defined(CONNECTIONPOINT_ARRAY_SIZE)
- #define CONNECTIONPOINT_ARRAY_SIZE 5
- #endif
-
- #if !defined(OLETEXT)
- #define OLETEXT(x) L ## x
- #endif
-
- #if !defined(OLETRACE)
- #define OLETRACE TDebugHlpr<TCHAR>::TRACE
- #endif
-
- #if !defined(OLECHECK)
- #define OLECHECK(hrexpr) TDebugHlpr<TCHAR>::HRCHECK(hrexpr, #hrexpr, __FILE__, __LINE__)
- #endif
-
- #if !defined(_ASSERTE)
- #define _ASSERTE(expr) do { \
- if (!(expr) && TDebugHlpr<TCHAR>::ASSERTE(#expr, __FILE__, __LINE__) == IDCANCEL) \
- ::DebugBreak(); \
- } while (0)
- #endif
-
- // Version of _ASSERTE usable within inline functions
- // i.e. Does not have do/while construct which is not allowed in inline functions currently
- //
- #if !defined(_ASSERTE_)
- #define _ASSERTE_(expr) ((expr) ? (0) : TDebugHlpr<TCHAR>::ASSERTE(#expr, __FILE__, __LINE__))
- #endif
-
-
- // TRACE/ASSERT/CHECK Helpers
- //
- template <class T>
- class TDebugHlpr
- {
- public:
- static void __cdecl TRACE (T* szFormat, ...);
- static HRESULT HRCHECK(HRESULT hr, const char *expr, const char* file = 0, int line = 0);
- static int ASSERTE(const char *expr, const char* file = 0, int line = 0);
- static void THROW (const char *msg);
- static int PROMPT (const char *caption, const char *msg);
-
- // Determines whether we display a MsgBox. When 'false' we simply
- // throw an exception.
- //
- static bool PromptOnAssertFailure;
- static bool PromptOnHrCheckFailure;
- };
-
-
- // Governs how OLECHECK and _ASSERTE are handled - when false we refrain to display a
- // MsgBox and simply throw an exception. If your code relies on try/catch to handle
- // these errors, you can disable prompting.
- //
- template <class T>
- bool TDebugHlpr<T>::PromptOnAssertFailure = false;
- template <class T>
- bool TDebugHlpr<T>::PromptOnHrCheckFailure= true;
-
-
- // Implementation of TRACE
- //
- template <class T>
- void __cdecl TDebugHlpr<T>::TRACE(T* szFormat, ...)
- {
- va_list args;
- va_start(args, szFormat);
- int bufSize;
- TCHAR szBuffer[_MAX_PATH*2];
- bufSize = wvsprintf(szBuffer, szFormat, args);
- _ASSERTE(bufSize < sizeof(szBuffer));
- ::OutputDebugString(szBuffer);
- va_end(args);
- }
-
- // OLECHECK - Throw an exception if !SUCCEEDED(hr)
- //
- template <class T>
- HRESULT __cdecl TDebugHlpr<T>::HRCHECK(HRESULT hr, const char* expr, const char* file, int line)
- {
- if (!SUCCEEDED(hr))
- {
- #if !defined(ClassesHPP)
- static
- #endif
- TCHAR szMsg[_MAX_PATH*2];
-
- if (!file)
- file = "";
-
- LPVOID msg = 0;
- if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, hr,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), LPTSTR(&msg), 0, 0) && (msg != 0))
- {
- ::wsprintf(szMsg, "'%s': %s @ %s/%d", expr, LPTSTR(msg), file, line);
- ::LocalFree(msg);
- }
- else
- ::wsprintf(szMsg, _T("(%s) Error: %lX (%ld) @ %s/%d"), expr, LONG(hr), LONG(hr), file, line);
-
- int i = IDYES;
- if (PromptOnHrCheckFailure)
- i = PROMPT("HRESULT Failure", szMsg);
- if (i == IDYES)
- THROW(szMsg);
- else if (i == IDCANCEL)
- ::DebugBreak();
- // NOTE: IDNO - implies we keep chugging along
- }
-
- return hr;
- }
-
- // _ASSERTE helper return MB_YES, MB_NO or MB_CANCEL
- //
- template <class T>
- int TDebugHlpr<T>::ASSERTE(const char* expr, const char* file, int line)
- {
- #if !defined(ClassesHPP)
- static
- #endif
- TCHAR msg[_MAX_PATH*2];
- ::wsprintf(msg, "%s @ %s/%d", LPTSTR(expr), file, line);
-
- int i = IDYES;
-
- if (PromptOnAssertFailure)
- i = PROMPT("Assertion Failure", msg);
-
- if (i == IDYES)
- {
- ::wsprintf(msg, "%s failed - %s/%d", expr, file, line);
- THROW(msg);
- }
- return i;
- }
-
- // Helper used to throw an exception
- //
- template <class T>
- void TDebugHlpr<T>::THROW(const char* msg)
- {
- // Use VCL class, if VCL headers have been seen
- //
- #if defined(ClassesHPP)
- throw Exception(AnsiString(msg));
- #else
- throw msg;
- #endif
- }
-
- // Helper used to display a MessageBox
- //
- template <class T>
- int TDebugHlpr<T>::PROMPT(const char* caption, const char* msg)
- {
- TCHAR szMsg[_MAX_PATH*2];
- wsprintf(szMsg, "%s\nPress [Y]es to terminate, [N]o to continue and [C]ancel to Debug", msg);
- return ::MessageBox(0, szMsg, caption, MB_TASKMODAL|MB_ICONQUESTION|MB_YESNOCANCEL);
- }
-
-
- // TPtrBase
- // Base class for automation pointer management. Provides basic implementation for
- // smart pointer object.
- //
- template<class T>
- class TPtrBase
- {
- public:
- // Methods implementing pointer semantics
- //
- T& operator * () const { _ASSERTE_(m_ptr); return *m_ptr; }
- operator T* () const { return m_ptr;}
- bool operator !() const { return m_ptr == 0; }
- T* operator->() const { _ASSERTE_(m_ptr); return m_ptr; }
- T** operator &()/*const*/ { return &m_ptr; }
-
- // Comparison operators
- //
- bool operator == (T *rhs) const { return m_ptr == rhs;}
- bool operator == (const TPtrBase<T> &rhs) const { return m_ptr == rhs.m_ptr; }
- bool operator != (T *rhs) const { return m_ptr != rhs;}
- bool operator != (const TPtrBase<T> &rhs) const { return m_ptr != rhs.m_ptr; }
-
- protected:
- TPtrBase() : m_ptr(0) {}
- TPtrBase(T* p) : m_ptr(p) {}
-
- T* get () const { return m_ptr; }
- T* release () { return reset(0); }
- T* reset (T* p = 0) { T* tmp = m_ptr; m_ptr = p; return tmp; }
-
- // Actual data
- //
- T* m_ptr;
-
- private:
- // Prevent new/delete
- //
- void* operator new(size_t);
- void operator delete(void *p){/*::delete p;*/};
- };
-
-
- // TPtr: Smart pointer object for non-array pointers
- //
- template<class T>
- class TPtr : public TPtrBase<T>
- {
- public:
- TPtr() : TPtrBase<T>() {}
- TPtr(T* src) : TPtrBase<T>(src) {}
- TPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
- ~TPtr() {clear(0);}
-
- // Assignment operators
- //
- TPtr& operator = (TPtr<T>& src)
- {
- // Transfer ownership of pointer to receiver
- //
- reset(src.release());
- return *this;
- }
- TPtr& operator = (T* src)
- {
- clear(src);
- return *this;
- }
-
- // Clear object - free pointer
- //
- void clear(T *src)
- {
- if (m_ptr)
- delete m_ptr;
- m_ptr = src;
- }
- };
-
-
- // TAPtr: Smart pointer object for array new'ed memory
- //
- template<class T>
- class TAPtr : public TPtrBase<T>
- {
- public:
- TAPtr() : TPtrBase<T>() {}
- TAPtr(T src[]) : TPtrBase<T>(src) {}
- TAPtr(TPtr<T>& src) : TPtrBase<T>(src.release()) {}
- ~TAPtr() {clear(0);}
-
- // Assignment operators
- //
- TAPtr& operator = (TAPtr<T>& src)
- {
- // Transfer ownership of pointer to receiver
- //
- reset(src.release());
- return *this;
- }
- TAPtr& operator = (T src[])
- {
- clear(src);
- return *this;
- }
-
- // Subscript operator (for array)
- //
- T& operator [](int i) const
- {
- _ASSERTE_(m_ptr);
- return m_ptr[i];
- }
-
- // Clear object - free pointer
- //
- void clear(T src[])
- {
- if (m_ptr)
- delete []m_ptr;
- m_ptr = src;
- }
- };
-
-
- // TInitOle: Simple object to initialize and unintialize Ole in a safe fashion
- //
- class TInitOle
- {
- public:
- TInitOle()
- {
- init = SUCCEEDED(::CoInitialize(0));
- }
- ~TInitOle()
- {
- if (init)
- ::CoUninitialize();
- }
-
- // Methods to test whether initialization was succcessful
- //
- operator bool () const
- {
- return init;
- }
- int operator ! () const
- {
- return init == false;
- }
-
- protected:
- // Flags if initialization was successful
- //
- bool init;
-
- private:
- // Prevent accidental copy to ensure equal numbers of Init/UnInit
- //
- TInitOle(const TInitOle&);
- TInitOle& operator = (const TInitOle&);
- };
-
-
- // Helper class used to create Default Interface Wrapper of CoClasses
- // (Used by Code generated by TLIBIMP)
- //
- class CoClassCreator
- {
- public:
- // Enhanced version of CoCreateInstance that handles failure due to CLSCTX_REMOTESERVER Flag
- //
- static HRESULT CoCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv)
- {
- HRESULT hr;
-
- // Define NO_REMOTE_BINDING if you do not want to try to bind to a remote server
- //
- #if !defined(NO_REMOTE_BINDING)
- hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER, riid, ppv);
-
- // If succeeded, or failed for reasons other than invalid arguments
- //
- if (SUCCEEDED(hr) || hr != E_INVALIDARG)
- return hr;
- #endif
-
- // Call CoCreateInstance, this time masking off CLSCTX_REMOTE_SERVER
- //
- hr = ::CoCreateInstance(rclsid, 0, CLSCTX_SERVER & ~CLSCTX_REMOTE_SERVER, riid, ppv);
- return hr;
- }
- };
-
-
- // Generic COM Interface wrapper
- // Performs proper AddRef/Release when object is copied, assigned to and deleted
- //
- template <class T>
- class TComInterface
- {
- public:
- TComInterface() : intf(0)
- {}
-
- // NOTE: The default behaviour of the constructor is not to AddRef the interface
- // pointer parameter. This is appropriate if the interface was obtained
- // has already been addRef'ed - as when retrieving a Font property.
- //
- TComInterface(T* p, bool addRef = false)
- {
- if (((intf = p) != 0) && addRef)
- intf->AddRef();
- }
-
- TComInterface(const TComInterface<T>& src)
- {
- if ((intf = src.intf) != 0)
- intf->AddRef();
- }
-
- ~TComInterface()
- {
- Reset();
- }
-
- operator T* () const
- {
- return intf;
- }
-
- T& operator*()
- {
- _ASSERTE_(intf!=0);
- return *intf;
- }
-
- // NOTE: You must explicitly Reset() any held interface pointers before invoking
- // the &operator (presumably to store another interface in the object)
- //
- T** operator & ()
- {
- _ASSERTE_(intf==0);
- return &intf;
- }
-
- T* operator->() const
- {
- _ASSERTE_(intf != 0);
- return intf;
- }
-
- T* operator->()
- {
- _ASSERTE_(intf != 0);
- return intf;
- }
-
- void Reset(T* p = 0)
- {
- if (intf)
- intf->Release();
- intf=p;
- }
-
- void Bind(T* p, bool addRef = false)
- {
- if (p && addRef)
- p->AddRef();
- Reset(p);
- }
-
- void Unbind()
- {
- Reset(0);
- }
-
- // NOTE: The assignment operator does *NOT* addRef the interface pointer being
- // assigned to this object.
- //
- TComInterface<T>& operator=(T* p)
- {
- Bind(p);
- return *this;
- }
-
- TComInterface<T>& operator=(const TComInterface<T>& src)
- {
- if (src.intf != 0)
- src.intf->AddRef();
- Reset(src.intf);
- }
-
- bool operator ! () const
- {
- return (intf == 0);
- }
-
-
- bool IsBound() const
- {
- return !!(*this);
- }
-
- protected:
- T* intf;
- };
-
- // Typedefs for standard interfaces
- //
- typedef TComInterface<IUnknown> TCOMIUnknown;
- typedef TComInterface<IDispatch> TCOMIDispatch;
-
- // Just in case this class is used solely for helper objects and
- // not for Automation
- //
- #if !defined(UTILCLS_NO_AUTOMATION)
-
- // Helper class for cases where VARIANT* or VARIANT& is expected for optional parameters
- //
- class TNoParam
- {
- public:
- TNoParam()
- {
- ::VariantInit(&m_Variant);
- m_Variant.vt = VT_ERROR;
- V_ERROR(&m_Variant) = DISP_E_PARAMNOTFOUND;
- }
- ~TNoParam()
- {
- ::VariantClear(&m_Variant);
- }
- operator VARIANT* ()
- {
- return &m_Variant;
- }
- operator VARIANT& ()
- {
- return m_Variant;
- }
-
- private:
- VARIANT m_Variant;
- };
-
-
- // The following ensures that Automation Drivers are not tied to VCL's Variant
- // Any VARIANT wrapper which exposes ctr, assignment op, and conversion op. for
- // Automation compatible types will do.
- //
- #if !defined __VARIANTOBJ_DEFINED
- #define __VARIANTOBJ_DEFINED
- typedef System::Variant VARIANTOBJ;
- #endif
-
- // Base class that exposes basic behaviour of our array of Variants
- //
- class TAutoArgsBase
- {
- protected:
- TAutoArgsBase(VARIANTOBJ *pVariant, int count) : m_Variant(pVariant), m_Count(count)
- {}
-
- public:
- VARIANTOBJ& operator[](int index) const
- {
- // NOTE: It's OK to use Count - there's an extra Variant for return result
- // Zero'th entry's reserved for return value.
- //
- _ASSERTE_(index <= m_Count);
- _ASSERTE_(index >= 0);
-
- // Make up for C++ vs. Basic reverse indexing
- //
- return m_Variant[index ? (m_Count+1-index) : 0];
- }
-
- VARIANT* GetRetVal() const
- {
- return (VARIANT*)(m_Variant);
- }
-
- VARIANTOBJ& GetRetVariant()
- {
- return *m_Variant;
- }
-
- VARIANT* GetArgs() const
- {
- return (VARIANT*)(m_Variant+1);
- }
-
- int GetCount() const
- {
- return m_Count;
- }
-
- private:
- TAutoArgsBase(const TAutoArgsBase&);
- TAutoArgsBase& operator=(const TAutoArgsBase&);
-
- VARIANTOBJ *m_Variant;
- int m_Count;
- };
-
-
- // TAutoArgs - Encapsulates array of Variants. Use for Invoke calls
- //
- template <int Count>
- class TAutoArgs : public TAutoArgsBase
- {
- public:
- TAutoArgs();
- ~TAutoArgs();
-
- private:
- // Allocate an extra Variant. It's the first entry and
- // it is reserved for return result. The rest are for parameters
- //
- VARIANTOBJ m_Array[Count+1];
- };
-
-
- // Build an array of Count (actualy Count+1, extra one for return value)
- // of VARIANTs.
- //
- template <int Count>
- TAutoArgs<Count>::TAutoArgs() : TAutoArgsBase(m_Array, Count)
- {}
-
-
- // Cleanup array of Variants
- //
- template <int Count>
- TAutoArgs<Count>::~TAutoArgs()
- {}
-
-
- // Enumeration describing DISPATCH type
- //
- enum DispatchFlag
- {
- dfMethod = DISPATCH_METHOD,
- dfPropGet = DISPATCH_PROPERTYGET,
- dfPropPut = DISPATCH_PROPERTYPUT,
- dfPropPutRef= DISPATCH_PROPERTYPUTREF
- };
-
- // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
- // Used by DispInterface Code Generated by TLIBIMP
- //
- template <class T>
- HRESULT OutRetValSetterPtr(T* retVal, TAutoArgsBase& args, HRESULT hr)
- {
- if (SUCCEEDED(hr))
- *retVal = args.GetRetVariant();
- return hr;
- }
-
- // Sets the value in the returnVariant to the retVal variable if SUCCEEDED(hr)
- // Used by DispInterface Code Generated by TLIBIMP
- template <class T>
- HRESULT OutRetValSetterRef(T& retVal, TAutoArgsBase& args, HRESULT hr)
- {
- if (SUCCEEDED(hr))
- retVal = args.GetRetVariant();
- return hr;
- }
-
-
- // Base class of AutoDrivers - provides an optional parameter
- //
- template <class DISPINTF>
- class TAutoDriverBase
- {
- public:
- static TNoParam OptParam;
- };
-
- // Static/shared instance of 'Optional Parameters'
- //
- template <class T>
- TNoParam TAutoDriverBase<T>::OptParam;
-
- // TAutoDriver - DispInterface Automation Proxy Driver
- //
- template <class DISPINTF>
- class TAutoDriver : public TAutoDriverBase<IDispatch>
- {
- public:
- TAutoDriver(LCID lcid = LOCALE_SYSTEM_DEFAULT);
- TAutoDriver(const TAutoDriver<DISPINTF> &src);
- ~TAutoDriver();
-
- // Bind via various mechanisms & Unbind
- // NOTE: Does *NOT* AddRef interface
- //
- void Bind(DISPINTF *pintf);
- HRESULT Bind(LPUNKNOWN punk);
- HRESULT Bind(const GUID& guid);
- HRESULT Bind(LPCWSTR progid);
-
- // Bind to running copy of Server
- //
- HRESULT BindToActive(const GUID& guid);
- HRESULT BindToActive(LPCWSTR propid);
-
- // Unbind from DispInterface
- //
- void Unbind(bool release = true);
-
- // Assignment of interface to object implies Bind to interface
- //
- TAutoDriver<DISPINTF>& operator =(DISPINTF *pintf)
- {
- Bind(pintf);
- return *this;
- }
-
- // Return Dispatch Interface
- //
- operator DISPINTF*() const;
- bool IsBound() const;
-
- // Allows access to interface being held
- // NOTE: Useful when dealing with dual interfaces
- // Using '->' yields Vtable call while '.' yields Invoke call
- DISPINTF* operator -> ()
- {
- return m_Dispatch;
- }
-
- // Return address of interface
- //
- DISPINTF** operator & ()
- {
- // Can take address (to presumably stuff new interface pointer) only if
- // not currently Bound;
- _ASSERTE_(m_Dispatch==0);
- return &m_Dispatch;
- }
-
- // Wrappers of IDispatch methods
- //
- HRESULT GetIDsOfNames(LPCWSTR name, DISPID &id);
- HRESULT Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal = true);
- HRESULT Invoke(DispatchFlag dFlags, DISPID dispId, TAutoArgsBase* args, bool hasRetVal = true);
-
- // Procedures with/without parameters
- //
- void OleProcedure(DISPID dispId, TAutoArgsBase& args)
- {
- Invoke(dfMethod, dispId, &args, false);
- }
- void OleProcedure(DISPID dispid)
- {
- Invoke(dfMethod, dispid, 0, false);
- }
-
- // FUnctions with/without parameters
- HRESULT OleFunction(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfMethod, dispid, &args, true);
- }
- HRESULT OleFunction(DISPID dispid)
- {
- return Invoke(dfMethod, dispid, 0, false);
- }
-
- // Property put (always has parameters)
- HRESULT OlePropertyPut(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfPropPut, dispid, &args, false);
- }
-
- // Property get (always has parameters, even if just TAutoArgs<0>)
- HRESULT OlePropertyGet(DISPID dispid, TAutoArgsBase& args)
- {
- return Invoke(dfPropGet, dispid, &args, true);
- }
-
- // Property get that returns VARIANT
- VARIANTOBJ OlePropertyGet(DISPID dispid);
-
- protected:
- DISPINTF *m_Dispatch; // Disp Interface Pointer
- LCID m_lcid; // Locale for DispId lookup & Invoke
- EXCEPINFO m_ExcepInfo; // Exception Structure
- UINT m_ErrArg; // Index of erroneous argument
- TInitOle m_InitOle; // Ensure OLE's Initialied
- };
-
-
- // Ctr & Dtr of Automation Driver class
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::TAutoDriver(LCID lcid) : m_Dispatch(0), m_lcid(lcid)
- {}
-
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::TAutoDriver(const TAutoDriver<DISPINTF> &src)
- {
- // NOTE: We do not copy the Exception, ErrArg or InitOle object
- // We simply clear them out
- m_ErrArg = 0;
- ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
-
- // Copy Interface and AddRefCount
- m_Dispatch = src.m_Dispatch;
- if (m_Dispatch)
- m_Dispatch->AddRef();
-
- // Copy Locale
- m_lcid = src.m_lcid;
- }
-
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::~TAutoDriver()
- {
- Unbind();
- }
-
- // Bind via Dispatch Interface
- // NOTE: Does *NOT* AddRef interface
- //
- template <class DISPINTF> void
- TAutoDriver<DISPINTF>::Bind(DISPINTF *pintf)
- {
- Unbind();
- m_Dispatch = pintf;
- }
-
- // Bind via IUnknown
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(LPUNKNOWN punk)
- {
- _ASSERTE(punk);
- HRESULT hr = E_POINTER;
- if (punk)
- {
- DISPINTF *disp;
- hr = punk->QueryInterface(IID_IDispatch, (LPVOID*)&disp);
- if (SUCCEEDED(hr))
- Bind(disp);
- }
- return hr;
- }
-
- // Bind via GUID
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(const GUID& clsid)
- {
- LPUNKNOWN punk = 0;
- HRESULT hr = CoClassCreator::CoCreateInstance(clsid, IID_IUnknown, (LPVOID*)&punk);
- if (SUCCEEDED(hr))
- {
- // We should have a valid interface pointer
- //
- _ASSERTE(punk);
-
- // Run Object - just in case
- //
- hr = ::OleRun(punk);
-
- // Bind to running IUnknown
- //
- if (SUCCEEDED(hr))
- hr = Bind(punk);
-
- // Release IUnknown
- //
- punk->Release();
- }
- return hr;
- }
-
- // Bind via ProgId
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Bind(LPCWSTR progid)
- {
- GUID clsid;
- HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
- if (SUCCEEDED(hr))
- return Bind(clsid);
- return hr;
- }
-
- // Bind to running copy of Object of this CLSID
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::BindToActive(const GUID& guid)
- {
- LPUNKNOWN punk = 0;
- HRESULT hr = ::GetActiveObject(guid, 0, &punk);
- if (SUCCEEDED(hr))
- return Bind(punk);
- return hr;
- }
-
- // Bind to running copy of object with the specified progId
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::BindToActive(LPCWSTR progid)
- {
- CLSID clsid;
- HRESULT hr = ::CLSIDFromProgID(progid, &clsid);
- if (SUCCEEDED(hr))
- return BindToActive(clsid);
- return hr;
- }
-
- // Release Dispatch Interface
- //
- template <class DISPINTF> void
- TAutoDriver<DISPINTF>::Unbind(bool release = true)
- {
- if (release && m_Dispatch)
- m_Dispatch->Release();
- m_Dispatch = 0;
- }
-
- // Return Dispatch Interface
- //
- template <class DISPINTF>
- TAutoDriver<DISPINTF>::operator DISPINTF* () const
- {
- return m_Dispatch;
- }
-
- // Returns Boolean indicating whether we're currently bound to the Server
- //
- template <class DISPINTF> bool
- TAutoDriver<DISPINTF>::IsBound() const
- {
- return m_Dispatch != 0;
- }
-
- // Encapsulation of IDispatch->GetIDsOfNames
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::GetIDsOfNames(LPCWSTR name, DISPID &id)
- {
- _ASSERTE(name);
- _ASSERTE(IsBound());
- return m_Dispatch->GetIDsOfNames(IID_NULL, (LPWSTR*)(&name), 1, m_lcid, &id);
- }
-
- // Invoke specified 'name'
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, LPCWSTR name, TAutoArgsBase* args, bool hasRetVal = true)
- {
- DISPID dispid;
- HRESULT hr = GetIDsOfNames(name, dispId);
- if (SUCCEEDED(hr))
- hr = Invoke(dFlags, dispid, args);
- return hr;
- }
-
- // Invoke specified 'DispId'
- //
- template <class DISPINTF> HRESULT
- TAutoDriver<DISPINTF>::Invoke(DispatchFlag dFlags, DISPID dispid, TAutoArgsBase* args, bool hasRetVal = true)
- {
- _ASSERTE(IsBound());
-
- VARIANT* retVal = 0;
-
- // Having return value implies an Args array (even if it contains only one
- // variant for the return value).
- //
- _ASSERTE((hasRetVal==false && args==0) ||
- (hasRetVal==false && args!=0) ||
- (hasRetVal==true && args!=0));
-
- // Setup return VARIANT
- // NOTE: PROPERTYPUTs do not return a result
- //
- if (!(dFlags & (dfPropPut|dfPropPutRef)) && hasRetVal)
- retVal = args->GetRetVal();
-
- // Special DispId for Property Puts
- //
- static DISPID DispIdPropertyPut = DISPID_PROPERTYPUT;
-
- // Setup DISPATCH parameters
- //
- DISPPARAMS params;
- ::ZeroMemory(¶ms, sizeof(params));
-
- // Set parameters (Note: PropPut[Ref] expected to have Count)
- if (args && args->GetCount())
- {
- params.cArgs = args->GetCount();
- params.rgvarg= args->GetArgs();
-
- // Handle PROPERTYPUT
- // NOTE: Assumes no named-arguments params have been setup
- //
- if (dFlags & (dfPropPut|dfPropPutRef))
- {
- params.cNamedArgs = 1;
- params.rgdispidNamedArgs = &DispIdPropertyPut;
- }
- }
-
- // Reset Error Information
- m_ErrArg = 0;
- ::ZeroMemory(&m_ExcepInfo, sizeof(m_ExcepInfo));
-
- // Invoke
- HRESULT hr = m_Dispatch->Invoke(dispid, IID_NULL, m_lcid, WORD(dFlags), ¶ms,
- retVal, &m_ExcepInfo, &m_ErrArg);
- // Output a little trace
- OLETRACE("Inv(%d) %s, 0x%lX, retVT(0x%X), ErrArg(%d)\n",
- dispid, SUCCEEDED(hr) ? "OK" : "FL", LONG(hr),
- retVal ? retVal->vt : VT_NULL, m_ErrArg);
- // Return result
- return hr;
- }
-
-
- // Property Get that returns a Variant
- //
- template <class DISPINTF> VARIANTOBJ
- TAutoDriver<DISPINTF>::OlePropertyGet(DISPID dispid)
- {
- TAutoArgs<0> args;
- OlePropertyGet(dispid, args);
- return args.GetRetVariant();
- }
-
- // TDispIdBase - Base class used by TDispId; allows us to have only one copy of the
- // flag governing whether DISPID should be looked up
- template <class T>
- class TDispIdBase
- {
- public:
- static bool m_AlwaysGetDispid;
- };
-
- // This flag triggers a lookup even if the object was pass a valid dispid!
- //
- template <class T>
- bool TDispIdBase<T>::m_AlwaysGetDispid = false;
-
- // TDispId - Class used to retrieve and cache a DISPID
- //
- template<class DISPINTF = IDispatch>
- class TDispId : public TDispIdBase<IDispatch>
- {
- public:
- TDispId(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName, DISPID id= DISPID_UNKNOWN) : m_DispId(id),
- m_HResult(S_OK)
- {
-
- if (id == DISPID_UNKNOWN || m_AlwaysGetDispid)
- m_HResult = GetID(dispatch, pName);
- _ASSERTE_(SUCCEEDED(m_HResult));
- }
-
- TDispId(DISPID id) : m_DispId(id), m_HResult(S_OK)
- {}
-
- HRESULT GetID(TAutoDriver<DISPINTF>& dispatch, LPCWSTR pName)
- {
- return dispatch.GetIDsOfNames(pName, m_DispId);
- }
-
- operator DISPID() const
- {
- return m_DispId;
- }
-
- HRESULT GetResult() const
- {
- return m_HResult;
- }
-
-
- protected:
- DISPID m_DispId;
- HRESULT m_HResult;
- };
-
- #endif // UTILCLS_NO_AUTOMATION
-
- #endif __UTILCLS_H
-
-
-